export interface Province {
  code: string
  name: string
  cities: Record<string, Cities>
}

export function isProvince(data: any): data is Province {
  return 'cities' in data
}

export interface Cities {
  code: string
  name: string
  districts: Record<string, string>
}
export function isCities(data: any): data is Cities {
  return 'districts' in data
}

function transformAddress(data?: Record<string, Province | Cities | string>) {
  return data
    && Object
      .values(data)
      .reduce<withChildren<{ label: string; value: string }>[]>(
        (previousValue, currentValue) => {
          if (typeof currentValue === 'string') {
            previousValue.push({
              label: currentValue,
              value: currentValue,
            })
          }
          else {
            const { name } = currentValue

            previousValue.push({
              label: name,
              value: name,
              children: isProvince(currentValue)
                ? transformAddress(currentValue.cities)
                : isCities(currentValue)
                  ? transformAddress(currentValue.districts)
                  : undefined,
            })
          }
          return previousValue
        },
        [],
      )
}

async function useAddress(): Promise<ReturnType<typeof transformAddress>>
async function useAddress<R>(transformer: ((data: Record<string, Province | Cities | string>) => R)): Promise<R>
async function useAddress<R>(transformer?: ((data: Record<string, Province | Cities | string>) => R)) {
  const data = await (await fetch('//unpkg.com/china-location/dist/location.json')).json() as Record<string, Province>
  return (transformer || transformAddress)(data)
}

export default useAddress
